package com.ease.dao.vo;

import org.springframework.jdbc.core.namedparam.AbstractSqlParameterSource;
import org.springframework.jdbc.core.namedparam.SqlParameterSource;

import com.ease.actionscript.Remoting;
import com.ease.common.vo.Ordering;
import com.ease.common.vo.Pagination;
import com.ease.dao.DataAccessObjectConst;
import com.ease.dao.util.DataAccessObjectUtil;

/**
 * 
 * @author nathanleewei
 * 
 */
public class PaginationSqlParameterSource extends AbstractSqlParameterSource implements DataAccessObjectConst {

	@Remoting(false)
	private SqlParameterSource sqlParameterSource;

	private Ordering ordering;

	private int skipResult = RAW_SKIP_RESULT;;

	private int maxResult = RAW_MAX_RESULT;

	public PaginationSqlParameterSource() {
	}

	public PaginationSqlParameterSource(Object parameter, Ordering ordering, int skipResult, int maxResult) {
		this.init(parameter, ordering);
		this.setSkipResult(skipResult);
		this.setMaxResult(maxResult);
	}

	@SuppressWarnings("unchecked")
	public PaginationSqlParameterSource(Object parameter, Ordering ordering, Pagination<?> pagination) {
		this.init(parameter, ordering);
		if (null == pagination) {
			pagination = new Pagination();
		}
		this.setSkipResult(pagination.getStart());
		this.setMaxResult(pagination.getStart() + pagination.getSize());
	}

	public PaginationSqlParameterSource(Object parameter, Ordering ordering) {
		this(parameter, ordering, null);
	}

	public PaginationSqlParameterSource(Object parameter) {
		this(parameter, null);
	}

	private void init(Object parameter, Ordering ordering) {
		this.setSqlParameterSource(DataAccessObjectUtil.safeSqlParameterSource(parameter));
		this.setOrdering(ordering);
	}

	public Object getValue(String paramName) throws IllegalArgumentException {
		if (SKIP_RESULTS.equals(paramName)) {
			if (this.skipResult > RAW_SKIP_RESULT) {
				return new Integer(this.skipResult);
			}
			return null;
		} else if (MAX_RESULTS.equals(paramName)) {
			if (this.skipResult > RAW_SKIP_RESULT && this.maxResult >= this.skipResult) {
				return new Integer(this.maxResult);
			}
			return null;
		} else if (ORDER_BY.equals(paramName)) {
			if (null != this.ordering) {
				return this.ordering.orderClause();
			}
			return null;
		}
		if (null != sqlParameterSource) {
			return this.sqlParameterSource.getValue(paramName);
		}
		return null;
	}

	public boolean hasValue(String paramName) {
		if (SKIP_RESULTS.equals(paramName)) {
			if (this.skipResult > RAW_SKIP_RESULT) {
				return true;
			}
			return false;
		} else if (MAX_RESULTS.equals(paramName)) {
			if (this.skipResult > RAW_SKIP_RESULT && this.maxResult >= this.skipResult) {
				return true;
			}
			return false;
		} else if (ORDER_BY.equals(paramName)) {
			if (null != this.ordering) {
				return true;
			}
			return false;
		}
		if (null != sqlParameterSource) {
			return this.sqlParameterSource.hasValue(paramName);
		}
		return false;
	}

	/**
	 * @return the sqlParameterSource
	 */
	public SqlParameterSource getSqlParameterSource() {
		return sqlParameterSource;
	}

	/**
	 * @param sqlParameterSource
	 *            the sqlParameterSource to set
	 */
	public void setSqlParameterSource(SqlParameterSource sqlParameterSource) {
		this.sqlParameterSource = sqlParameterSource;
	}

	/**
	 * @return the ordering
	 */
	public Ordering getOrdering() {
		return ordering;
	}

	/**
	 * @param ordering
	 *            the ordering to set
	 */
	public void setOrdering(Ordering ordering) {
		this.ordering = ordering;
	}

	/**
	 * @return the skipResult
	 */
	public int getSkipResult() {
		return skipResult;
	}

	/**
	 * @param skipResult
	 *            the skipResult to set
	 */
	public void setSkipResult(int skipResult) {
		this.skipResult = skipResult;
	}

	/**
	 * @return the maxResult
	 */
	public int getMaxResult() {
		return maxResult;
	}

	/**
	 * @param maxResult
	 *            the maxResult to set
	 */
	public void setMaxResult(int maxResult) {
		this.maxResult = maxResult;
	}

}
